#property copyright "Copyright 2024"
#property link      ""
#property version   "1.00"
#property description "Market Condition Analyzer with Trade Signals"

// 引入必要的库
#include <Trade\Trade.mqh>

// 枚举定义
enum RISK_PROFILE {
    CONSERVATIVE = 1,    // 保守
    MODERATE = 2,        // 适中
    AGGRESSIVE = 3       // 激进
};

enum MARKET_CONDITION {
    RANGING = 1,         // 震荡市
    TRENDING = 2,        // 趋势市
    VOLATILE = 3         // 高波动
};

// 输入参数
input string TechnicalSettings = "===== 技术分析设置 =====";
input int TrendPeriod = 200;                 // 趋势判断周期
input int VolatilityPeriod = 20;             // 波动率计算周期
input bool UseADX = true;                    // 使用ADX指标
input int ADXPeriod = 14;                    // ADX周期
input double ADXThreshold = 25;              // ADX阈值

// 全局变量
MARKET_CONDITION g_currentMarketCondition = RANGING;
MARKET_CONDITION g_previousMarketCondition = RANGING;  // 添加前一个市场状态
double g_volatility = 0;
datetime g_lastSignalTime = 0;
int g_lastStateChangeBar = 0;  // 添加状态变化时的K线位置
int g_lastSignalType = -1;  // -1: 无信号, 1: 买入信号, -1: 卖出信号

// 指标句柄
int ma200Handle;
int ma50Handle;
int ma20Handle;
int adxHandle;
int rsiHandle;
int bbHandle;

//+------------------------------------------------------------------+
//| Expert initialization function                                     |
//+------------------------------------------------------------------+
int OnInit() {
    // 初始化指标句柄
    ma200Handle = iMA(_Symbol, PERIOD_CURRENT, TrendPeriod, 0, MODE_SMA, PRICE_CLOSE);
    ma50Handle = iMA(_Symbol, PERIOD_CURRENT, 50, 0, MODE_SMA, PRICE_CLOSE);
    ma20Handle = iMA(_Symbol, PERIOD_CURRENT, 20, 0, MODE_SMA, PRICE_CLOSE);
    adxHandle = iADX(_Symbol, PERIOD_CURRENT, ADXPeriod);
    rsiHandle = iRSI(_Symbol, PERIOD_CURRENT, 14, PRICE_CLOSE);
    bbHandle = iBands(_Symbol, PERIOD_CURRENT, 20, 2, 0, PRICE_CLOSE);
    
    // 检查指标句柄是否创建成功
    if(ma200Handle == INVALID_HANDLE || ma50Handle == INVALID_HANDLE || 
       ma20Handle == INVALID_HANDLE || adxHandle == INVALID_HANDLE || 
       rsiHandle == INVALID_HANDLE || bbHandle == INVALID_HANDLE) {
        Print("指标初始化失败");
        return INIT_FAILED;
    }
    
    return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert deinitialization function                                   |
//+------------------------------------------------------------------+
void OnDeinit(const int reason) {
    // 释放指标句柄
    IndicatorRelease(ma200Handle);
    IndicatorRelease(ma50Handle);
    IndicatorRelease(ma20Handle);
    IndicatorRelease(adxHandle);
    IndicatorRelease(rsiHandle);
    IndicatorRelease(bbHandle);
    
    // 清理图表对象
    ObjectsDeleteAll(0, "Signal_");
}

//+------------------------------------------------------------------+
//| Expert tick function                                              |
//+------------------------------------------------------------------+
void OnTick() {
    // 更新市场状态
    UpdateMarketCondition();
    
    // 寻找交易机会
    FindNewTradeOpportunities();
}

//+------------------------------------------------------------------+
//| 更新市场状态                                                      |
//+------------------------------------------------------------------+
void UpdateMarketCondition() {
    double adx[], plusDI[], minusDI[];
    ArraySetAsSeries(adx, true);
    ArraySetAsSeries(plusDI, true);
    ArraySetAsSeries(minusDI, true);
    
    // 获取ADX值
    if(CopyBuffer(adxHandle, 0, 0, 2, adx) <= 0) return;
    if(CopyBuffer(adxHandle, 1, 0, 2, plusDI) <= 0) return;
    if(CopyBuffer(adxHandle, 2, 0, 2, minusDI) <= 0) return;
    
    // 计算波动率
    double volatility = GetCurrentVolatility();
    double avgVolatility = GetAverageVolatility();
    
    // 计算趋势持续性
    int trendCount = 0;
    double close[];
    ArraySetAsSeries(close, true);
    if(CopyClose(_Symbol, PERIOD_CURRENT, 0, 4, close) <= 0) return;
    
    for(int i = 0; i < 3; i++) {
        if(close[i] > close[i+1]) trendCount++;
        else trendCount--;
    }
    
    // 保存前一个市场状态
    g_previousMarketCondition = g_currentMarketCondition;
    
    // 判断市场状态
    if(adx[0] > ADXThreshold * 1.2 && MathAbs(trendCount) >= 2) {
        g_currentMarketCondition = TRENDING;
        Print("市场状态：趋势市 - ADX:", adx[0], " 趋势计数:", trendCount);
    }
    else if(volatility > avgVolatility * 1.8) {
        g_currentMarketCondition = VOLATILE;
        Print("市场状态：高波动 - 当前波动率:", volatility, " 平均波动率:", avgVolatility);
    }
    else {
        g_currentMarketCondition = RANGING;
        Print("市场状态：震荡市");
    }
    
    // 检查市场状态是否发生变化，并且距离上次状态变化至少5根K线
    // if(g_currentMarketCondition != g_previousMarketCondition) {
    //     int currentBar = iTime(_Symbol, PERIOD_CURRENT, 0);
    //     if(currentBar - g_lastStateChangeBar >= 5) {
    //         DrawMarketStateTransition();
    //         g_lastStateChangeBar = currentBar;
    //     }
    // }
}

//+------------------------------------------------------------------+
//| 绘制市场状态转换分界线                                            |
//+------------------------------------------------------------------+
void DrawMarketStateTransition() {
    string objName = "StateTransition_" + TimeToString(TimeCurrent());
    datetime currentTime = TimeCurrent();
    double currentPrice = iClose(_Symbol, PERIOD_CURRENT, 0);
    
    // 创建垂直线
    ObjectCreate(0, objName, OBJ_VLINE, 0, currentTime, 0);
    ObjectSetInteger(0, objName, OBJPROP_COLOR, clrYellow);
    ObjectSetInteger(0, objName, OBJPROP_STYLE, STYLE_DASH);
    ObjectSetInteger(0, objName, OBJPROP_WIDTH, 2);
    ObjectSetInteger(0, objName, OBJPROP_SELECTABLE, false);
    
    // 创建状态标签
    string labelName = objName + "_Label";
    string stateText = "";
    
    if(g_currentMarketCondition == TRENDING) {
        stateText = "趋势市开始";
        ObjectSetInteger(0, objName, OBJPROP_COLOR, clrBlue);
    }
    else if(g_currentMarketCondition == RANGING) {
        stateText = "震荡市开始";
        ObjectSetInteger(0, objName, OBJPROP_COLOR, clrOrange);
    }
    else if(g_currentMarketCondition == VOLATILE) {
        stateText = "高波动开始";
        ObjectSetInteger(0, objName, OBJPROP_COLOR, clrRed);
    }
    
    // 添加文本标签
    ObjectCreate(0, labelName, OBJ_TEXT, 0, currentTime, currentPrice);
    ObjectSetString(0, labelName, OBJPROP_TEXT, stateText);
    ObjectSetInteger(0, labelName, OBJPROP_COLOR, ObjectGetInteger(0, objName, OBJPROP_COLOR));
    ObjectSetInteger(0, labelName, OBJPROP_FONTSIZE, 8);
    ObjectSetInteger(0, labelName, OBJPROP_ANCHOR, ANCHOR_LEFT);
    
    // 添加警报
    string alertMessage = StringFormat("%s - %s", _Symbol, stateText);
    Alert(alertMessage);
    PlaySound("alert.wav");
}

//+------------------------------------------------------------------+
//| 寻找交易机会                                                      |
//+------------------------------------------------------------------+
void FindNewTradeOpportunities() {
    // 检查最小时间间隔（至少间隔5分钟）
    if(TimeCurrent() - g_lastSignalTime < 300) return;
    
    // 获取指标数据
    double ma200[], ma50[], ma20[], adx[], plusDI[], minusDI[], rsi[], bbUpper[], bbLower[];
    ArraySetAsSeries(ma200, true);
    ArraySetAsSeries(ma50, true);
    ArraySetAsSeries(ma20, true);
    ArraySetAsSeries(adx, true);
    ArraySetAsSeries(plusDI, true);
    ArraySetAsSeries(minusDI, true);
    ArraySetAsSeries(rsi, true);
    ArraySetAsSeries(bbUpper, true);
    ArraySetAsSeries(bbLower, true);
    
    if(CopyBuffer(ma200Handle, 0, 0, 2, ma200) <= 0) return;
    if(CopyBuffer(ma50Handle, 0, 0, 2, ma50) <= 0) return;
    if(CopyBuffer(ma20Handle, 0, 0, 2, ma20) <= 0) return;
    if(CopyBuffer(adxHandle, 0, 0, 2, adx) <= 0) return;
    if(CopyBuffer(adxHandle, 1, 0, 2, plusDI) <= 0) return;
    if(CopyBuffer(adxHandle, 2, 0, 2, minusDI) <= 0) return;
    if(CopyBuffer(rsiHandle, 0, 0, 2, rsi) <= 0) return;
    if(CopyBuffer(bbHandle, 1, 0, 2, bbUpper) <= 0) return;
    if(CopyBuffer(bbHandle, 2, 0, 2, bbLower) <= 0) return;
    
    double currentPrice = iClose(_Symbol, PERIOD_CURRENT, 0);
    
    // 根据市场状态执行不同的策略
    switch(g_currentMarketCondition) {
        case RANGING:
            ExecuteRangingStrategy(currentPrice, rsi[0], bbUpper[0], bbLower[0]);
            break;
        case TRENDING:
            ExecuteTrendingStrategy(currentPrice, ma200[0], ma50[0], ma20[0], adx[0], plusDI[0], minusDI[0]);
            break;
        case VOLATILE:
            // 在高波动市场中不产生信号
            break;
    }
}

//+------------------------------------------------------------------+
//| 执行震荡市策略                                                    |
//+------------------------------------------------------------------+
void ExecuteRangingStrategy(double currentPrice, double rsi, double bbUpper, double bbLower) {
    if(rsi < 30 && currentPrice < bbLower) {
        if(g_lastSignalType != 1) {  // 避免重复信号
            DrawSignal("BUY", currentPrice, "震荡");
            g_lastSignalType = 1;
            g_lastSignalTime = TimeCurrent();
        }
    }
    else if(rsi > 70 && currentPrice > bbUpper) {
        if(g_lastSignalType != -1) {  // 避免重复信号
            DrawSignal("SELL", currentPrice, "震荡");
            g_lastSignalType = -1;
            g_lastSignalTime = TimeCurrent();
        }
    }
}

//+------------------------------------------------------------------+
//| 执行趋势市策略                                                    |
//+------------------------------------------------------------------+
void ExecuteTrendingStrategy(double currentPrice, double ma200, double ma50, double ma20, 
                            double adx, double plusDI, double minusDI) {
    // 上升趋势条件
    bool isUptrend = (ma20 > ma50 && ma50 > ma200) && 
                    (adx > ADXThreshold * 1.2) && 
                    (plusDI > minusDI) && 
                    (currentPrice > ma20 && currentPrice > ma50 && currentPrice > ma200);
    
    // 下降趋势条件
    bool isDowntrend = (ma20 < ma50 && ma50 < ma200) && 
                      (adx > ADXThreshold * 1.2) && 
                      (minusDI > plusDI) && 
                      (currentPrice < ma20 && currentPrice < ma50 && currentPrice < ma200);
    
    if(isUptrend && g_lastSignalType != 1) {
        DrawSignal("BUY", currentPrice, "趋势");
        g_lastSignalType = 1;
        g_lastSignalTime = TimeCurrent();
    }
    else if(isDowntrend && g_lastSignalType != -1) {
        DrawSignal("SELL", currentPrice, "趋势");
        g_lastSignalType = -1;
        g_lastSignalTime = TimeCurrent();
    }
}

//+------------------------------------------------------------------+
//| 在图表上绘制信号                                                  |
//+------------------------------------------------------------------+
void DrawSignal(string type, double price, string signalType) {
    string objName = "Signal_" + TimeToString(TimeCurrent());
    
    // 创建箭头对象
    ObjectCreate(0, objName, OBJ_ARROW, 0, TimeCurrent(), price);
    
    // 设置箭头属性
    if(type == "BUY") {
        ObjectSetInteger(0, objName, OBJPROP_ARROWCODE, 233);  // 上箭头
        ObjectSetInteger(0, objName, OBJPROP_COLOR, clrGreen);
    }
    else {
        ObjectSetInteger(0, objName, OBJPROP_ARROWCODE, 234);  // 下箭头
        ObjectSetInteger(0, objName, OBJPROP_COLOR, clrRed);
    }
    
    ObjectSetInteger(0, objName, OBJPROP_WIDTH, 2);
    ObjectSetInteger(0, objName, OBJPROP_SELECTABLE, false);
    
    // 添加文本标签
    string labelName = objName + "_Label";
    ObjectCreate(0, labelName, OBJ_TEXT, 0, TimeCurrent(), price);
    ObjectSetString(0, labelName, OBJPROP_TEXT, type + "(" + signalType + ")");
    ObjectSetInteger(0, labelName, OBJPROP_COLOR, type == "BUY" ? clrGreen : clrRed);
    ObjectSetInteger(0, labelName, OBJPROP_FONTSIZE, 8);
    ObjectSetInteger(0, labelName, OBJPROP_ANCHOR, ANCHOR_LEFT);

    // 添加警报通知
    string alertMessage = StringFormat("%s信号 - %s%s 价格: %.5f", 
                                     _Symbol, 
                                     type == "BUY" ? "买入" : "卖出",
                                     signalType,
                                     price);
    Alert(alertMessage);  // 弹出提醒
    PlaySound("alert.wav");  // 播放声音提醒
}

//+------------------------------------------------------------------+
//| 计算当前波动率                                                    |
//+------------------------------------------------------------------+
double GetCurrentVolatility() {
    double high[], low[];
    ArraySetAsSeries(high, true);
    ArraySetAsSeries(low, true);
    
    if(CopyHigh(_Symbol, PERIOD_CURRENT, 0, VolatilityPeriod, high) <= 0) return 0;
    if(CopyLow(_Symbol, PERIOD_CURRENT, 0, VolatilityPeriod, low) <= 0) return 0;
    
    double volatility = 0;
    for(int i = 0; i < VolatilityPeriod; i++) {
        volatility += MathAbs(high[i] - low[i]);
    }
    return volatility / VolatilityPeriod;
}

//+------------------------------------------------------------------+
//| 计算平均波动率                                                    |
//+------------------------------------------------------------------+
double GetAverageVolatility() {
    double high[], low[];
    ArraySetAsSeries(high, true);
    ArraySetAsSeries(low, true);
    
    if(CopyHigh(_Symbol, PERIOD_CURRENT, 0, VolatilityPeriod * 5, high) <= 0) return 0;
    if(CopyLow(_Symbol, PERIOD_CURRENT, 0, VolatilityPeriod * 5, low) <= 0) return 0;
    
    double sum = 0;
    for(int i = 0; i < VolatilityPeriod * 5; i++) {
        sum += MathAbs(high[i] - low[i]);
    }
    return sum / (VolatilityPeriod * 5);
} 